<docs>
---
order: 5
title: 自定义筛选菜单
---

## zh-CN

通过 `customFilterDropdown` 定义自定义的列筛选功能，并实现一个搜索列的示例。

</docs>

<template>
    <j-table :data-source="data" :columns="columns">
        <template #headerCell="{ column }">
            <template v-if="column.key === 'name'">
                <span style="color: #1890ff">Name</span>
            </template>
        </template>
        <template
            #customFilterDropdown="{
                setSelectedKeys,
                selectedKeys,
                confirm,
                clearFilters,
                column,
            }"
        >
            <div style="padding: 8px">
                <j-input
                    ref="searchInput"
                    :placeholder="`Search ${column.dataIndex}`"
                    :value="selectedKeys[0]"
                    style="width: 188px; margin-bottom: 8px; display: block"
                    @change="
                        (e) =>
                            setSelectedKeys(
                                e.target.value ? [e.target.value] : [],
                            )
                    "
                    @pressEnter="
                        handleSearch(selectedKeys, confirm, column.dataIndex)
                    "
                />
                <j-button
                    type="primary"
                    size="small"
                    style="width: 90px; margin-right: 8px"
                    @click="
                        handleSearch(selectedKeys, confirm, column.dataIndex)
                    "
                >
                    <template #icon><SearchOutlined /></template>
                    Search
                </j-button>
                <j-button
                    size="small"
                    style="width: 90px"
                    @click="handleReset(clearFilters)"
                >
                    Reset
                </j-button>
            </div>
        </template>
        <template #customFilterIcon="{ filtered }">
            <search-outlined
                :style="{ color: filtered ? '#108ee9' : undefined }"
            />
        </template>
        <template #bodyCell="{ text, column }">
            <span v-if="searchText && searchedColumn === column.dataIndex">
                <template
                    v-for="(fragment, i) in text
                        .toString()
                        .split(
                            new RegExp(
                                `(?<=${searchText})|(?=${searchText})`,
                                'i',
                            ),
                        )"
                >
                    <mark
                        v-if="
                            fragment.toLowerCase() === searchText.toLowerCase()
                        "
                        :key="i"
                        class="highlight"
                    >
                        {{ fragment }}
                    </mark>
                    <template v-else>{{ fragment }}</template>
                </template>
            </span>
        </template>
    </j-table>
</template>

<script>
import { SearchOutlined } from '@ant-design/icons-vue';
import { defineComponent, reactive, ref, toRefs } from 'vue';
const data = [
    {
        key: '1',
        name: 'John Brown',
        age: 32,
        address: 'New York No. 1 Lake Park',
    },
    {
        key: '2',
        name: 'Joe Black',
        age: 42,
        address: 'London No. 1 Lake Park',
    },
    {
        key: '3',
        name: 'Jim Green',
        age: 32,
        address: 'Sidney No. 1 Lake Park',
    },
    {
        key: '4',
        name: 'Jim Red',
        age: 32,
        address: 'London No. 2 Lake Park',
    },
];

export default defineComponent({
    components: {
        SearchOutlined,
    },
    setup() {
        const state = reactive({
            searchText: '',
            searchedColumn: '',
        });

        const searchInput = ref();

        const columns = [
            {
                title: 'Name',
                dataIndex: 'name',
                key: 'name',
                customFilterDropdown: true,
                onFilter: (value, record) =>
                    record.name
                        .toString()
                        .toLowerCase()
                        .includes(value.toLowerCase()),
                onFilterDropdownVisibleChange: (visible) => {
                    if (visible) {
                        setTimeout(() => {
                            searchInput.value.focus();
                        }, 100);
                    }
                },
            },
            {
                title: 'Age',
                dataIndex: 'age',
                key: 'age',
            },
            {
                title: 'Address',
                dataIndex: 'address',
                key: 'address',
                customFilterDropdown: true,
                onFilter: (value, record) =>
                    record.address
                        .toString()
                        .toLowerCase()
                        .includes(value.toLowerCase()),
                onFilterDropdownVisibleChange: (visible) => {
                    if (visible) {
                        setTimeout(() => {
                            searchInput.value.focus();
                        }, 100);
                    }
                },
            },
        ];

        const handleSearch = (selectedKeys, confirm, dataIndex) => {
            confirm();
            state.searchText = selectedKeys[0];
            state.searchedColumn = dataIndex;
        };

        const handleReset = (clearFilters) => {
            clearFilters({ confirm: true });
            state.searchText = '';
        };

        return {
            data,
            columns,
            handleSearch,
            handleReset,
            searchInput,
            ...toRefs(state),
        };
    },
});
</script>
<style scoped>
.highlight {
    background-color: rgb(255, 192, 105);
    padding: 0px;
}
</style>
